package com.uminho.http;

import java.io.EOFException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.StreamCorruptedException;
import java.util.ArrayList;
import java.util.Iterator;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.util.Log;

import com.uminho.egendme.Login;
import com.uminho.objects.Appointment;
import com.uminho.objects.Bookmark;
import com.uminho.tools.ApplicationContext;




/****c* http/InternalStorage
 * DESCRIPTION
 * Classe responsável por oferecer suporte aos métodos de armazenamento interno
 *
 ****
 */

public class InternalStorage {
	private static String file = "token";
	private static String appointmentfile = "appointmenta";
	private static String bookmarkfile = "bookmarka";


	
	/****f* InternalStorage/saveToken
	 * DESCRIPTION
	 * Método executado para salvar o token na memória interna
	 * INPUTS
	 * Token
	 * RESULT
	 * Booleano que indica se o token foi salvo com sucesso na memória interna
	 ****
	 */
	
	
	public static boolean saveToken(String token) {
		Context c = ApplicationContext.c;
		FileOutputStream fos = null;
		try {
			fos = c.openFileOutput(file, Context.MODE_PRIVATE);
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return false;
		}
		try {
			fos.write(token.getBytes());
			fos.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return false;
		}

		return true;
	}

	/**           
	 * @return String with resulting token or empty string if fail to open file
	 */
	
	/****f* InternalStorage/openToken
	 * DESCRIPTION
	 * Método executado para abrir o token salvo na memória interna
	 * RESULT
	 * String com o token presente na memória interna
	 ****
	 */
	public static String openToken() {
		Context c = ApplicationContext.c;
		String result = "";
		FileInputStream fis = null;
		try {
			fis = c.openFileInput(file);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
			return "";

		}
		int ch;
		StringBuffer fileContent = new StringBuffer("");
		try {
			while ((ch = fis.read()) != -1)
				fileContent.append((char) ch);
		} catch (IOException e) {
			e.printStackTrace();
			return "";
		}
		result = new String(fileContent);
		return result;
	}

	/**
	 * Tests if token exists
	 * 
	 * @return true if toke exists
	 */
	
	/****f* InternalStorage/existsToken
	 * DESCRIPTION
	 * Método executado para verificar se existe um token na memória interna
	 * RESULT
	 * Booleano que indica se existe o token na memória interna
	 ****
	 */
	public static boolean existsToken() {
		Context c = ApplicationContext.c;
		FileInputStream fis = null;
		String result="";
		try {
			fis = c.openFileInput(file);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
			return false;
		}

		int ch;
		StringBuffer fileContent = new StringBuffer("");
		try {
			while ((ch = fis.read()) != -1)
				fileContent.append((char) ch);
		} catch (IOException e) {
			e.printStackTrace();
			return false;
		}
		result = new String(fileContent);
		if(result.equals("")) return false;
		else return true;
	}

	/**
	 * delete existing token
	 * 
	 * @return true if token deleted
	 */
	
	/****f* InternalStorage/deleteToken
	 * DESCRIPTION
	 * Método executado para apagar o token da memória interna
	 * RESULT
	 * Token deixa de existir na memória interna
	 ****
	 */
	public static boolean deleteToken() {
		String token="";
		Context c = ApplicationContext.c;
		FileOutputStream fos = null;
		try {
			fos = c.openFileOutput(file, Context.MODE_PRIVATE);
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return false;
		}
		try {
			fos.write(token.getBytes());
			fos.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return false;
		}

		return true;
	}
	
	/****f* InternalStorage/saveAppointments
	 * DESCRIPTION
	 * Método executado para salvar a lista de appointments
	 * INPUTS
	 * Lista de appointments
	 * RESULT
	 * Lista de appointments guardada em ficheiro
	 ****
	 */
	public static boolean saveAppointments(ArrayList<Appointment> ap){
		Context c = ApplicationContext.c;
		FileOutputStream fos = null;
		ObjectOutputStream outputStream = null;
		try {
			fos = c.openFileOutput(appointmentfile, Context.MODE_PRIVATE);
			outputStream = new ObjectOutputStream(fos);
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return false;
		}catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return false;
		}
		
		try {
			Iterator it = ap.iterator();
			while(it.hasNext()){
				outputStream.writeObject((Appointment)it.next());
			}
			
			if (outputStream != null) {
                outputStream.flush();
                outputStream.close();
            }
			return true;
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return false;
		}

	}
	
	/****f* InternalStorage/readAppointments
	 * DESCRIPTION
	 * Método executado para receber appointments guardados em ficheiro
	 * RESULT
	 * Recebe lista de appointments guardada em ficheiro
	 ****
	 */
	public static ArrayList<Appointment> readAppointments() {
		ArrayList<Appointment> apps = new ArrayList<Appointment>();
		Context c = ApplicationContext.c;
        ObjectInputStream inputStream = null;
        FileInputStream fis = null;
		try {
			fis = c.openFileInput(appointmentfile);
			 //Construct the ObjectInputStream object
            inputStream = new ObjectInputStream(fis);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
			return null;
		} catch (StreamCorruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return null;
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return null;
		}
		
        try {
            
           
            Object obj = null;
            
            while ((obj = inputStream.readObject()) != null ) {
            	if(obj instanceof Appointment && obj != null){
            	Appointment ap = (Appointment)obj;
            	apps.add(ap);
            	Log.d("ler" , ap.getComment());
            	}
        	}
            
        } catch (ClassNotFoundException ex) {
            ex.printStackTrace();
        } catch (FileNotFoundException ex) {
            ex.printStackTrace();
        } catch (EOFException eof) {
            //eof.printStackTrace();
            Log.d("aqui", eof.toString());
            try {
				inputStream.close();
				 fis.close();
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
            return apps;
        
        }catch (Exception ex) {
            ex.printStackTrace();
        }
            //Close the ObjectInputStream
            try {
                if (inputStream != null) {
                    inputStream.close();
                }
                if(fis != null){
                	fis.close();
                }
            } catch (Exception ex) {
                ex.printStackTrace();
                
            }
        
        return apps;
    }
	/****f* InternalStorage/readBookmarks
	 * DESCRIPTION
	 * Método executado para receber favoritos guardados em ficheiro
	 * RESULT
	 * Recebe lista de favoritos guardada em ficheiro
	 ****
	 */
	public static ArrayList<Bookmark> readBookmarks() {
		ArrayList<Bookmark> apps = new ArrayList<Bookmark>();
		Context c = ApplicationContext.c;
        ObjectInputStream inputStream = null;
        FileInputStream fis = null;
		try {
			fis = c.openFileInput(bookmarkfile);
			 //Construct the ObjectInputStream object
            inputStream = new ObjectInputStream(fis);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
			return null;
		} catch (StreamCorruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return null;
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return null;
		}
		
        try {
            
           
            Object obj = null;
            
            while ((obj = inputStream.readObject()) != null ) {
            	if(obj instanceof Bookmark && obj != null){
            		Bookmark ap = (Bookmark)obj;
            	apps.add(ap);
            	Log.d("ler" , ap.getTitle());
            	}
        	}
            
        } catch (ClassNotFoundException ex) {
            ex.printStackTrace();
        } catch (FileNotFoundException ex) {
            ex.printStackTrace();
        } catch (EOFException eof) {
            //eof.printStackTrace();
           // Log.d("aqui", eof.toString());
            try {
				inputStream.close();
				 fis.close();
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
            return apps;
        
        }catch (Exception ex) {
            ex.printStackTrace();
        }
            //Close the ObjectInputStream
            try {
                if (inputStream != null) {
                    inputStream.close();
                }
                if(fis != null){
                	fis.close();
                }
            } catch (Exception ex) {
                ex.printStackTrace();
                
            }
        
        return apps;
    }
	/****f* InternalStorage/saveBookmarks
	 * DESCRIPTION
	 * Método executado para salvar a lista de favoritos
	 * INPUTS
	 * Lista de favoritos
	 * RESULT
	 * Lista de favoritos guardada em ficheiro
	 ****
	 */
	public static boolean saveBookmarks(ArrayList<Bookmark> ap){
		Context c = ApplicationContext.c;
		FileOutputStream fos = null;
		ObjectOutputStream outputStream = null;
		try {
			fos = c.openFileOutput(bookmarkfile, Context.MODE_PRIVATE);
			outputStream = new ObjectOutputStream(fos);
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return false;
		}catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return false;
		}
		
		try {
			Iterator<Bookmark> it = ap.iterator();
			while(it.hasNext()){
				outputStream.writeObject((Bookmark)it.next());
			}
			
			if (outputStream != null) {
                outputStream.flush();
                outputStream.close();
            }
			return true;
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return false;
		}

	}
	/**
	 * Clears token, kill all activitie Tree of the context c and request login
	 * 
	 * @param c
	 */
	
	/****f* InternalStorage/deleteToken
	 * DESCRIPTION
	 * Método executado para apagar o token da memória interna
	 * INPUT
	 * Contexto da aplicação
	 * RESULT
	 * Token deixa de existir na memória interna e o utilizador é enviado para a actividade de Login
	 ****
	 */
	public static void goLoggin(Context c) {
		deleteToken();
		Intent init = new Intent(c, Login.class);
		init.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
		c.startActivity(init);
		if(InternalStorage.class.isInstance(Activity.class));
		((Activity) c).finish();

	}
}
